#include <math.h>
#include <iostream>
#include <functional>

#define PI 3.14
using std::cout;
using std::endl;
using std::function;
using std::bind;


// 使用std::bind与std::function（基于对象的形式）实现上课所讲的Figure的例子的代码
#if 0
class Figure
{
    using DISPLAY = function<void(void)>;
    using AREA = function<double(void)>;
public:
    void set_display(const DISPLAY &display) { _display = display; }
    void set_area(const AREA &area) { _area = area; }
    virtual void display() const { _display(); }
    virtual double area() const { return _area(); }
private:
    DISPLAY _display;
    AREA _area;
};

// 矩形
class Rectangle
{
public:
    Rectangle(double length, double width) : _length(length), _width(width){}
    void display() const {
        cout << "长: " << _length;
        cout << ", 宽: " << _width;
        cout << endl;
    }
    double area() const { return _length * _width; }

private:
    double _length;
    double _width;
};
// 圆形
class Circle
{
public:
    Circle(double radius) : _radius(radius){} 
    void display() const {
        cout << "半径: " << _radius;
        cout << endl;
    }
    double area() const { return PI * pow(_radius, 2); }

private:
    double _radius;
};
// 三角形
class Triangle
{
public:
    Triangle(double a, double b, double c) : _a(a), _b(b), _c(c){}
    void display() const {
        cout << "a: " << _a;
        cout << ", b: " << _b;
        cout << ", c: " << _c;
        cout << endl;
    }
    double area() const {
        double l = (_a + _b + _c) / 2;
        return sqrt(l * (l - _a) * (l - _b) * (l - _c));
    }
private:
    double _a;
    double _b;
    double _c;
};

int main()
{
    cout << "===长方形===" << endl;
    Figure f1;
    f1.set_display(bind(&Rectangle::display, Rectangle(9, 8)));

    f1.display();
    f1.set_area(bind(&Rectangle::area, Rectangle(9, 8)));
    cout << f1.area() << endl << endl;


    cout << "===圆形===" << endl;
    Figure f2;
    f2.set_display(bind(&Circle::display, Circle(8)));

    f2.display();
    f2.set_area(bind(&Circle::area, Circle(8)));
    cout << f2.area() << endl << endl;


    cout << "===三角形===" << endl;
    Figure f3;
    f3.set_display(bind(&Triangle::display, Triangle(3, 8, 9)));

    f3.display();
    f3.set_area(bind(&Triangle::area, Triangle(3, 8, 9)));
    cout << f3.area() << endl << endl;

    return 0;
}
#endif


// 使用动态多态（面向对象的形式）实现上课所讲的Figure的例子的代码
#if 0
class Figure
{
public:
    virtual void display() const = 0; 
    virtual double area() const = 0;
};

// 矩形
class Rectangle
    : public Figure
{
public:
    Rectangle(double length, double width) : _length(length), _width(width){}
    void display() const override {
        cout << "长: " << _length;
        cout << ", 宽: " << _width;
        cout << endl;
    }
    double area() const override { return _length * _width; }

private:
    double _length;
    double _width;
};
// 圆形
class Circle
    : public Figure
{
public:
    Circle(double radius) : _radius(radius){} 
    void display() const override {
        cout << "半径: " << _radius;
        cout << endl;
    }
    double area() const override { return PI * pow(_radius, 2); }

private:
    double _radius;
};
// 三角形
class Triangle
    : public Figure
{
public:
    Triangle(double a, double b, double c) : _a(a), _b(b), _c(c){}
    void display() const override {
        cout << "a: " << _a;
        cout << ", b: " << _b;
        cout << ", c: " << _c;
        cout << endl;
    }
    double area() const override {
        double l = (_a + _b + _c) / 2;
        return sqrt(l * (l - _a) * (l - _b) * (l - _c));
    }
private:
    double _a;
    double _b;
    double _c;
};

int main()
{
    Rectangle r(9, 8);
    Circle c(8);
    Triangle t(3, 8, 9);
    Figure* fp;
    cout << "===长方形===" << endl;
    fp = &r;
    fp->display();
    cout << fp->area() << endl << endl;


    cout << "===圆形===" << endl;
    fp = &c;
    fp->display();
    cout << fp->area() << endl << endl;


    cout << "===三角形===" << endl;
    fp = &t;
    fp->display();
    cout << fp->area() << endl << endl;

    return 0;
}
#endif